#include "HttpUtil.h"
#include "httplib.h"

bool HttpUtil::GetRequestPath(std::string url, std::string& host, std::string& path)
{
	// 非http链接
	if (url.find("http://") == std::string::npos && url.find("https://") == std::string::npos) {
		return false;
	}

	// http://localhost:5700/a/b/c
	std::string prefix = url;
	std::string dir = "";
	int pos = prefix.find("http://");
	if (pos != std::string::npos)
	{
		pos = url.find("/", 7);
		prefix = url.substr(0, pos);
		dir = url.substr(pos);
	}
	else if (prefix.find("https://") != std::string::npos)
	{
		pos = url.find("/", 8);
		prefix = url.substr(0, pos);
		dir = url.substr(pos);
	}

	host = prefix;
	path = dir;
	return true;
}

bool HttpUtil::Download(std::string url, std::string file)
{
	try
	{
		// 获取请求路径
		std::string host;
		std::string path;
		if (!GetRequestPath(url, host, path))
		{
			return false;
		}

		// 打开文件
		std::ofstream ofs(file, std::ios::binary | std::ios::trunc);

		// 客户端定义
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
		httplib::SSLClient cli(host.c_str());
		//cli.set_ca_cert_path("./ca-bundle.crt");
		cli.enable_server_certificate_verification(false);
#else
		httplib::Client cli(host.c_str());
#endif	
		// 设置连接超时时间为5秒
		cli.set_connection_timeout(5);
		// 设置读取超时时间为10秒
		cli.set_read_timeout(10);

		// 下载文件
		httplib::Result res = cli.Get(
			path.c_str(),
			[&](const httplib::Response& response) {
			std::cerr << "http read:" << response.status << std::endl;
			return true;
		},
			[&](const char* data, size_t data_length) {
			std::string str_data = std::string(data, data_length);
			ofs << str_data;
			return true;
		});

		// 关闭文件
		ofs.close();

		// 返回结果
		return res->status == 200;
	}
	catch (std::exception e)
	{
		printf("http download error:%s\n", e.what());
	}
	catch (...)
	{
	}
	return false;
}

bool HttpUtil::Upload(std::string url, std::string file, std::string& body)
{
	try
	{
		// 获取请求路径
		std::string host;
		std::string path;
		if (!GetRequestPath(url, host, path))
		{
			return false;
		}

		// 读取文件内容
		std::ifstream fin(file.c_str(), std::ios::binary);
		std::ostringstream os;
		os << fin.rdbuf();
		std::string content = os.str();
		fin.close();

		// 文件名称
		boost::uuids::random_generator randomg;
		boost::uuids::uuid cid = randomg();
		std::string fileName = boost::uuids::to_string(cid);
		boost::algorithm::replace_all(fileName, "-", "");
		int pos = path.rfind(".");
		if (pos != -1)
		{
			fileName += path.substr(pos);
		}

		// 客户端定义
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
		httplib::SSLClient cli(host.c_str());
		//cli.set_ca_cert_path("./ca-bundle.crt");
		cli.enable_server_certificate_verification(false);
#else
		httplib::Client cli(host.c_str());
#endif	
		// 设置连接超时时间为5秒
		cli.set_connection_timeout(5);
		// 设置读取超时时间为10秒
		cli.set_read_timeout(30);

		// 上传内容
		httplib::MultipartFormDataItems items = {
			{
				"file", content,
				fileName.c_str(),
				"application/octet-stream"
			}
		};

		// 开始上传
		auto res = cli.Post(path.c_str(), items);
		if (!res || res->status != 200)
		{
			return false;
		}

		// 返回结果
		body = res->body;
		return true;
	}
	catch (std::exception e)
	{
		printf("http upload error:%s\n", e.what());
	}
	catch (...)
	{
	}
	return false;
}

bool HttpUtil::DoGet(std::string url, std::string& body)
{
	try
	{
		// 获取请求路径
		std::string host;
		std::string path;
		if (!GetRequestPath(url, host, path))
		{
			return false;
		}

		// 客户端定义
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
		httplib::SSLClient cli(host.c_str());
		//cli.set_ca_cert_path("./ca-bundle.crt");
		cli.enable_server_certificate_verification(false);
#else
		httplib::Client cli(host.c_str());
#endif	
		// 设置连接超时时间为5秒
		cli.set_connection_timeout(5);
		// 设置读取超时时间为10秒
		cli.set_read_timeout(10);

		// 开始请求
		auto res = cli.Get(path.c_str());
		if (!res || res->status != 200)
		{
			return false;
		}

		// 返回结果
		body = res->body;
		return true;
	}
	catch (std::exception e)
	{
		printf("http get error:%s\n", e.what());
	}
	catch (...)
	{
	}
	return false;
}

bool HttpUtil::DoGet(std::string url, std::map<std::string, std::string> headers, std::string& body)
{
	try
	{
		// 获取请求路径
		std::string host;
		std::string path;
		if (!GetRequestPath(url, host, path))
		{
			return false;
		}

		// 客户端定义
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
		httplib::SSLClient cli(host.c_str());
		//cli.set_ca_cert_path("./ca-bundle.crt");
		cli.enable_server_certificate_verification(false);
#else
		httplib::Client cli(host.c_str());
#endif	
		// 设置连接超时时间为5秒
		cli.set_connection_timeout(5);
		// 设置读取超时时间为10秒
		cli.set_read_timeout(10);

		// 携带参数请求
		httplib::Headers http_head;
		for (std::map<std::string, std::string>::iterator it = headers.begin(); it != headers.end(); ++it)
		{
			http_head.emplace(it->first, it->second);
		}

		// 开始请求
		auto res = cli.Get(path.c_str(), http_head);
		if (!res || res->status != 200)
		{
			return false;
		}

		// 返回结果
		body = res->body;
		return true;
	}
	catch (std::exception e)
	{
		printf("http get error:%s\n", e.what());
	}
	catch (...)
	{
	}
	return false;
}

bool HttpUtil::DoPost(std::string url, std::string json, std::string& body)
{
	try
	{
		// 获取请求路径
		std::string host;
		std::string path;
		if (!GetRequestPath(url, host, path))
		{
			return false;
		}

		// 客户端定义
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
		httplib::SSLClient cli(host.c_str());
		//cli.set_ca_cert_path("./ca-bundle.crt");
		cli.enable_server_certificate_verification(false);
#else
		httplib::Client cli(host.c_str());
#endif
		// 设置连接超时时间为5秒
		cli.set_connection_timeout(5);
		// 设置读取超时时间为10秒
		cli.set_read_timeout(10);

		// 创建header
		httplib::Headers headers = {
			{ "content-type", "application/json" }
		};

		// 开始请求
		auto res = cli.Post(path.c_str(), headers, json, "application/json");
		if (!res || res->status != 200)
		{
			return false;
		}

		// 返回结果
		body = res->body;
		return true;
	}
	catch (std::exception e)
	{
		printf("http get error:%s\n", e.what());
	}
	catch (...)
	{
	}
	return false;
}

bool HttpUtil::DoPost(std::string url, std::map<std::string, std::string> params, std::string& body)
{
	try
	{
		// 获取请求路径
		std::string host;
		std::string path;
		if (!GetRequestPath(url, host, path))
		{
			return false;
		}

		// 携带参数请求
		httplib::Params http_param;
		for (std::map<std::string, std::string>::iterator it = params.begin(); it != params.end(); ++it)
		{
			http_param.emplace(it->first, it->second);
		}

		// 客户端定义
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
		httplib::SSLClient cli(host.c_str());
		//cli.set_ca_cert_path("./ca-bundle.crt");
		cli.enable_server_certificate_verification(false);
#else
		httplib::Client cli(host.c_str());
#endif	
		// 设置连接超时时间为5秒
		cli.set_connection_timeout(5);
		// 设置读取超时时间为10秒
		cli.set_read_timeout(10);

		// 开始请求
		auto res = cli.Post(path.c_str(), http_param);
		if (!res || res->status != 200)
		{
			return false;
		}

		// 返回结果
		body = res->body;
		return true;
	}
	catch (std::exception e)
	{
		printf("http get error:%s\n", e.what());
	}
	catch (...)
	{
	}
	return false;
}